/*
 * Sonatype Nexus (TM) Open Source Version
 * Copyright (c) 2008-present Sonatype, Inc.
 * All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
 *
 * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
 * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
 *
 * Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
 * of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
 * Eclipse Foundation. All other trademarks are the property of their respective owners.
 */
import React from "react";
import {render, screen} from "@testing-library/react";
import {act} from "react-dom/test-utils";
import {when} from "jest-when";
import axios from "axios";
import TestUtils from "@sonatype/nexus-ui-plugin/src/frontend/src/interface/TestUtils";
import {APIConstants, ExtJS} from '@sonatype/nexus-ui-plugin';

import MalwareRemediation from './MalwareRemediation';
import {maliciousRiskOnDiskResponse, maliciousRiskOnDiskResponseWithCount0} from "../../widgets/riskondisk/MaliciousRiskOnDisk.testdata";
import FeatureFlags from "../../../constants/FeatureFlags";
import MaliciousRiskStrings from "../../../constants/pages/maliciousrisk/MaliciousRiskStrings";
import {helperFunctions} from "../../widgets/CELimits/UsageHelper";

const {MALICIOUS_RISK_ON_DISK} = APIConstants.REST.PUBLIC;
const {MALWARE_RISK_ON_DISK_ENABLED} = FeatureFlags;
const {MALICIOUS_RISK: {MALWARE_REMEDIATION, OPEN_SOURCE_MALWARE}} = MaliciousRiskStrings;
const {
  useThrottlingStatusValue,
  useGracePeriodEndsDate
} = helperFunctions;

jest.mock('axios', () => ({
  ...jest.requireActual('axios'),
  get: jest.fn()
}));


jest.mock('@sonatype/nexus-ui-plugin', () => ({
  ...jest.requireActual('@sonatype/nexus-ui-plugin'),
  ExtJS: {
    isProEdition: jest.fn(),
    state: jest.fn().mockReturnValue({
      getValue: jest.fn()
    }),
    useUser: jest.fn(),
    urlOf: jest.fn().mockImplementation((path) => 'https://testurl/' + path),
    useState: jest.fn()
  },
}));

const selectors = {
  ...TestUtils.selectors,
  getHeading: (t) => screen.getByRole('heading', {name: t}),
  queryLink: (t) => screen.queryByRole('link', {name: t}),
  queryText: (t) => screen.queryByText(t),
};

describe('MalwareRemediation', () => {
  beforeEach(() => {
    window.location.hash = '#browse/malwarerisk';
    ExtJS.useUser.mockReturnValue({'administrator': true});
    when(ExtJS.state().getValue)
        .calledWith(MALWARE_RISK_ON_DISK_ENABLED)
        .mockReturnValue(true);
    when(ExtJS.state().getValue)
        .calledWith('nexus.malware.count')
        .mockReturnValue(maliciousRiskOnDiskResponse);
    when(ExtJS.useState)
        .calledWith(useThrottlingStatusValue)
        .mockReturnValue('Under limits');
    when(ExtJS.useState)
        .calledWith(useGracePeriodEndsDate)
        .mockReturnValue(new Date(''));
  })

  it('renders malware component count', async () => {
    await act(async () => {
      render(<MalwareRemediation />);
    });

    expect(selectors.getHeading('Malware Risk')).toBeInTheDocument();
    expect(selectors.getHeading('1,234,567')).toBeInTheDocument();
    expect(selectors.getHeading('Malware Components Found')).toBeInTheDocument();
    expect(selectors.queryText(MALWARE_REMEDIATION.DESCRIPTION)).toBeInTheDocument();
  });

  it('renders malware component count when zero', async () => {
    when(ExtJS.state().getValue)
        .calledWith('nexus.malware.count')
        .mockReturnValue(maliciousRiskOnDiskResponseWithCount0);

    await act(async () => {
      render(<MalwareRemediation />);
    });

    expect(selectors.getHeading('0')).toBeInTheDocument();
    expect(selectors.getHeading('Malware Component Found')).toBeInTheDocument();
    expect(selectors.queryText(MALWARE_REMEDIATION.DESCRIPTION)).toBeInTheDocument();
  });

  it('renders remediation steps', async () => {
    await act(async () => {
      render(<MalwareRemediation />);
    });

    expect(selectors.queryText(MALWARE_REMEDIATION.REMEDIATION_STEPS.TITLE)).toBeInTheDocument();
    expect(selectors.queryText(MALWARE_REMEDIATION.REMEDIATION_STEPS.FIRST)).toBeInTheDocument();
    expect(selectors.queryText('Search your proxy repository to remove the components.')).toBeInTheDocument();
    expect(selectors.queryText('Learn how to protect your repository to keep developers from downloading Malware again.')).toBeInTheDocument();
    expect(selectors.queryLink('Download CSV')).toBeInTheDocument();
    expect(selectors.queryLink('Download CSV'))
        .toHaveAttribute('href', 'https://testurl/service/rest/v1/malicious-risk/malware-components-csv');
    expect(selectors.queryLink('Guide to removing malware')).toBeInTheDocument();
    expect(selectors.queryLink('Guide to removing malware'))
        .toHaveAttribute('href', 'https://links.sonatype.com/nexus-repository-firewall/malware-risk/guide-to-removing-malware');
    expect(selectors.queryLink('How to protect your repository from malware')).toBeInTheDocument();
    expect(selectors.queryLink('How to protect your repository from malware'))
        .toHaveAttribute('href', 'https://links.sonatype.com/nexus-repository-firewall/malware-risk/malware-risk');
  });

  it('renders open source malware info', async () => {
    await act(async () => {
      render(<MalwareRemediation />);
    });

    expect(selectors.getHeading(OPEN_SOURCE_MALWARE.TITLE)).toBeInTheDocument();
    expect(selectors.queryText('Open Source Malware in proxy repositories poses a critical risk to the integrity of the ' +
        'software supply chain, introducing malware such as credential harvesting, data exfiltration, backdoor, file system ' +
        'corruption leads to compromised applications, data breaches, and regulatory non-compliance.')).toBeInTheDocument();
    expect(selectors.queryText('Remediation requires immediate removal of infected components, identifying impacted ' +
        'dependencies, and Developers must be informed of the threat and prevented from accessing to compromised artifacts.')).toBeInTheDocument()
    expect(selectors.queryLink('Differentiating Software Vulnerabilities and Malware')).toBeInTheDocument();
    expect(selectors.queryLink('Differentiating Software Vulnerabilities and Malware'))
        .toHaveAttribute('href', 'https://links.sonatype.com/nexus-repository-firewall/malware-risk/vulnerabilities-and-malware');
  });
});
